#include "MyThread.h"
#include "MyTools.h"

MyThread::MyThread():mRunning(false)
{
    pthread_mutex_init(&mMutex, NULL);
}

MyThread::~MyThread()
{
    pthread_mutex_destroy(&mMutex);
}

void MyThread::Lock()
{
    pthread_mutex_lock (&mMutex);
}

void MyThread::Unlock()
{
    pthread_mutex_unlock (&mMutex);
}

void* MyThread::StartThread(void* pVoid)
{
    // thread start function when no Runnable is involved
    MyThread* aThread = static_cast<MyThread*>(pVoid);
    aThread->Run();
    return 0;
}

void MyThread::Start()
{
    if(mRunning) return;

    // initialize attribute object
    int status = pthread_attr_init(&mThreadAttribute);
    if(status)
    {
        MYLOG( "pthread_attr_init failed - " << status );
        exit(status);
    }

    // set the scheduling scope attribute
    status = pthread_attr_setscope(&mThreadAttribute,
                                   PTHREAD_SCOPE_SYSTEM);
    if(status)
    {
        MYLOG( "pthread_attr_setscope failed - " << status );
        exit(status);
    }

    status = pthread_create(&mThreadID, &mThreadAttribute,
                            MyThread::StartThread, (void*)this);
    if(status)
    {
        MYLOG( "pthread_create failed - " << status );
        exit(status);
    }

    status = pthread_attr_destroy(&mThreadAttribute);
    if(status)
    {
        MYLOG( "pthread_attr_destroy failed - " << status );
        exit(status);
    }

    mRunning = true;
}

void MyThread::Join()
{
    if(!mRunning) return;

    // A thread calling T.join() waits until thread T completes.
    int status = pthread_join(mThreadID, NULL);
    // result was already saved by thread start function
    if(status)
    {
        MYLOG("pthread_join failed - " << status);
        exit(status);
    }

    mRunning = false;
}
